/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.wpi.first.wpilibj.templates;

import com.sun.squawk.io.BufferedWriter;
import com.sun.squawk.microedition.io.FileConnection;
import edu.wpi.first.wpilibj.Timer;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Hashtable;
import java.util.Vector;
import javax.microedition.io.Connector;

/**
 * Class for recording telemetry data.
 * @author Laptop2010
 */
public class DataRecorder{

    private static DataRecorder m_instance = null;

    //data storage
    private Hashtable data;
    private Vector hashkeys;
    private Vector text;
    StringBuffer line = new StringBuffer(500);

    //file
    private String path;
    private FileConnection fcTelemetry;

    //timer
    private Timer timer;

    private boolean writeToFlashEnabled = true;

    private DataRecorder() {
	data = new Hashtable();
	hashkeys = new Vector(50);
        text = new Vector(1000);
	timer = new Timer();
    }

    /**
     * Get an instance of the DataRecorder.
     * Accepts the name of the telemetry file
     * as a parameter.
     * @param path
     * @return
     */
    public static DataRecorder getInstance(String path) {
	if (m_instance == null) {
	    m_instance = new DataRecorder();
	}
	if (path.length() > 0) {
	    m_instance.path = path;
	}
	return m_instance;
    }

    /**
     * Get an instance of the DataRecorder.
     * @return
     */
    public static DataRecorder getInstance() {
	return getInstance("");
    }

    /**
     * Registers a name which will be used as
     * a header in the outputted xcel csv.
     * @param name
     */
    public void createField(String name){
	if(!hashkeys.contains(name)){
	    hashkeys.addElement(name);
	}
    }

    /**
     * Registers names which will be used as
     * a header in the outputted xcel csv.
     */
    public void createField(String[] names){
        for(int i = 0; i < names.length; i++) {
                createField(names[i]);
	    }
    }

    /**
     * Method to write to a named field,
     * which must have been registered with
     * the createField() method.
     */
    public void record(String name, int value) {
	data.put(name, Integer.toString(value));
    }

     /**
     * Method to write to a named field,
     * which must have been registered with
     * the createField() method.
     */
    public void record(String name, double value) {
	data.put(name,formatDouble(value,5));
    }

    /**
     * Method to write to a named field,
     * which must have been registered with
     * the createField() method.
     */
    public void record(String name, String value) {
	data.put(name,value);
    }

    /**
     * Method to write to a named field,
     * which must have been registered with
     * the createField() method.
     */
    public void record(String name, boolean value) {
	data.put(name,(value)?"true":"false");
    }

    /**
     * Update the logging Vector with all
     * info that has been recorded.
     */
    public void log(){
	  
	   //make sure the line can store enough characters
	   line.delete(0,line.length());
	   
	   line.append(formatDouble(timer.get(),2));

	    //get the list of data
	    for (int i = 0; i < hashkeys.size(); i++) {
		line.append("," + (data.get((String) hashkeys.elementAt(i))));
	    }

	    //add the line to the vector
	    text.addElement(line.toString());

    }


    /**
     * Write all logged data to
     * the telemetry file.
     *
     * Warning: if this method is called before
     * the old log file is retrieved, that log
     * will be deleted!
     */
    public void writeToFile() {

	//do not write if not enabled
	if(!writeToFlashEnabled)return;

	try {

	    //delete the old file and open the new
	    fcTelemetry = (FileConnection)Connector.open(path,Connector.READ_WRITE);

	    if (fcTelemetry.exists()) {
		fcTelemetry.delete();
	    }
	    fcTelemetry.create();

	    OutputStream ost = fcTelemetry.openOutputStream();
	    BufferedWriter ostream = new BufferedWriter(new OutputStreamWriter(ost));


	    //for testing without robot
//	    fcTelemetry = new File(path);
//
//	    if (fcTelemetry.exists()) {
//		fcTelemetry.delete();
//	    }
//	    fcTelemetry.createNewFile();
//
//	    FileOutputStream ost = new FileOutputStream(fcTelemetry);
//	    BufferedWriter ostream = new BufferedWriter(new OutputStreamWriter(ost));


	    //print the header
	    ostream.write(createHeader());

	    ostream.newLine();
	    ostream.newLine();

	    //write the data
	    for(int i = 0; i < text.size(); i++){
		ostream.write((String)text.elementAt(i));
		ostream.newLine();
	    }

	    //close the stream
	    ostream.close();

            text.removeAllElements();

	} catch (IOException e) {
	    System.out.println(e.getMessage());
	}
    }

    /**
     * Change the name of the telemetry file.
     * @param path
     */
    public void setPath(String path) {
	this.path = path;
    }

    /**
     * Reset and start the timer (for timestamps)
     */
    public void startTimer(){
	timer.stop();
	timer.reset();
	timer.start();
    }

    public static String formatDouble(double number, int precision) {

        String formattedNumber = Double.toString(number);
	int point = formattedNumber.indexOf('.');

	//just quit if "." not found
	if(point == -1)return formattedNumber;

	if(!(formattedNumber.length() - point <= precision + 1))
	    formattedNumber = formattedNumber.substring(0,point + precision + 1);

	return formattedNumber;
    }

    private String createHeader(){

	StringBuffer header = new StringBuffer(100);

	header.append("Timestamp");

	for(int i = 0; i < hashkeys.size(); i++){
	    header.append("," + (String)hashkeys.elementAt(i));
	}

	return header.toString();
    }

    public void setWriteToFlashEnabled(boolean enabled){
        writeToFlashEnabled = enabled;
    }
}